package com.qdlc.p2p.biz.adapted.impl;

import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.qd.p2p.adapter.AdaptedRequestHandleService;
import com.qd.p2p.adapter.param.BankCardListForEnterpriseParameter;
import com.qd.p2p.adapter.param.BankCardListParameter;
import com.qd.p2p.adapter.response.BankCardListForEnterpriseResponse;
import com.qd.p2p.adapter.response.BankCardListResponse;
import com.qd.p2p.adapter.response.BankCardListResponse.Bank;
import com.qdlc.p2p.biz.adapted.AdaptedWithdrawService;
import com.qdlc.p2p.biz.service.AccountBankService;
import com.qdlc.p2p.biz.service.AccountCashService;
import com.qdlc.p2p.biz.service.AccountService;
import com.qdlc.p2p.common.constant.AccountCashStatus;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.LogTplNid;
import com.qdlc.p2p.common.core.ReturnResult;
import com.qdlc.p2p.common.util.DataUtils;
import com.qdlc.p2p.common.util.LogFactory;
import com.qdlc.p2p.common.util.NumberUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.common.util.code.MD5;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.dao.AccountBankDao;
import com.qdlc.p2p.dal.dto.Account;
import com.qdlc.p2p.dal.dto.AccountBank;
import com.qdlc.p2p.dal.dto.AccountCash;
import com.qdlc.p2p.dal.dto.SystemConfig;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserIdentify;
import com.qdlc.p2p.dal.util.SystemConfigs;
import com.qdlc.p2p.dal.util.UserTypeUtils;
import com.qdlc.p2p.dal.util.UserUtils;

/**
 * 功能描述: 资金提现抽象类
 * @author linya
 * @date 2016-4-22
 */
public abstract class AbstractAdaptedWithdrawService implements AdaptedWithdrawService{

	protected static final Logger log = LogFactory.CASH_LOGGER;
	
    @Resource
    protected AccountBankDao accountBankDao;

    @Autowired
    protected AdaptedRequestHandleService adaptedPayService;

    @Autowired
    protected AccountBankService accountBankService;

    @Resource
    protected AccountCashService accountCashService;

    @Resource
    protected AccountService accountService;

    /**
     * [提取] 提取页面信息
     *
     * @param user
     * @return
     */
    @Override
    public ReturnResult gotoNewCash(User user) {
    	
        //获取账户记录
        Account account = accountService.findAccountByUserId(user.getUserId());

        //获取银行卡记录
        AccountBank accountBank = null;
        List<AccountBank> bankList = accountBankDao.list(user.getUserId());
        if (bankList != null && bankList.size() > 0) {
            accountBank = bankList.get(0);
        }

        // 返回页面属性信息
        ReturnResult result = validCash(user, account, bankList);
        result.addExtra("canCash", result.isSuccess());
        result.addExtra("validCash", result.toMap());
        result.addExtra("bankNum", SystemConfigHelper.getIntegerValue(Nid.BANK_NUM));
        result.addExtra("bankList", bankList);
        result.addExtra("account", account);
        result.addExtra("accountBank", accountBank);

        return result;
    }

    private ReturnResult validCash(User user, Account account, List<AccountBank> bankList) {

        // 判断可用金额
        if (account.getUseMoney() <= 0) {
            return new ReturnResult("<div style='color:#c83e41;'>没有可用余额，目前不能提现！</div>");
        }

        // 判断银行卡
        if (bankList == null || bankList.size() == 0) {
            return new ReturnResult("<div style='color:#c83e41;'>请先添加银行卡！</div>");
        }

        //当天提现次数限制
        ReturnResult result = validSingleDayTime(user);
        if (result.isError()) {
            return result;
        }

        //当天提现额度限制
        boolean dayMaxAmountLimit = false;
        double singleDayAmount = 0;
        double singleDayMaxAmountLimit = 0;
        SystemConfig config = SystemConfigHelper.getSystemConfig(Nid.CASH_SINGLE_DAY_MAX_AMOUNT_LIMIT);
        if (config.getStatus() == 1) {
            dayMaxAmountLimit = true;
            singleDayAmount = accountCashService.getSingleDayAmount(user.getUserId());
            singleDayMaxAmountLimit = DataUtils.toDouble(config.getValue());
            if (singleDayAmount >= singleDayMaxAmountLimit) {
                return new ReturnResult("您今天提现已达限额" + NumberUtil.format2Str(singleDayMaxAmountLimit) + "元,明天再来!");
            }
        }

        result = new ReturnResult();

        // 当天可提取金额提示
        if (dayMaxAmountLimit) {
            double remain = singleDayMaxAmountLimit - singleDayAmount;
            if (remain > 0 && account.getUseMoney() > remain) {
                result.addExtra("singleDayMaxAmountStatus", true);
                result.addExtra("singleDayMaxAmountMsg", "您今天还可提现" + NumberUtil.format2Str(remain) + "元.");
            }
        }

        // 手续费信息提示
        config = SystemConfigHelper.getSystemConfig(Nid.CASH_FEE_COUNT_MIN);
        if (config.getStatus() == 1) {
            double cashMin = SystemConfigHelper.getDoubleValue(Nid.CASH_FEE_COUNT_MIN);
            // 申请中的提现
            int applyIntcount = accountCashService.getApplyingCount(user.getUserId());
            if (applyIntcount == 0 && account.getUseMoney() < cashMin) {
                result.addExtra("cashMinStatus", true);
                result.addExtra("cashMinMsg", "</br>您当前可用余额小于" + Math.round(cashMin) + "元,且没有其他提现操作,满足\"小额免费\"条件.</br>如需提现,请一次性提现,免提现手续费.");
            }
        }
        return result;
    }

    /**
     * [提取] 检测提取前置条件
     *
     * @param user   当前用户
     * @param money  提取金额
     * @param bankNo 提取银行卡
     * @param payPwd 交易密码
     * @return
     */
    @Override
    public ReturnResult doCashPreCondition(User user, double money, String bankNo, String payPwd) {

        // 检测实名认证
        UserIdentify userIdentify = UserUtils.getUserIdentify(user.getUserId());
        if (userIdentify.getRealNameStatus() != 1) {
            return new ReturnResult("请先进行实名认证");
        }
        if (userIdentify.getMobilePhoneStatus() != 1) {
            return new ReturnResult("请先进行手机认证");
        }

        // 检测银行卡、交易密码
        if (StringUtil.isBlank(user.getPayPwd())) {
            return new ReturnResult("请设置交易密码!");
        }
        if (StringUtil.isBlank(bankNo)) {
            return new ReturnResult("请选择提现银行卡!");
        }
        if (StringUtil.isBlank(payPwd)) {
            return new ReturnResult("请填写交易密码!");
        }
        if (money <= 0) {
            return new ReturnResult("请填写提现金额!");
        }
        if (!user.getPayPwd().equals(MD5.encode(payPwd))) {
            return new ReturnResult("交易密码不正确!");
        }

        //检测可用金额
        ReturnResult result = validUseMoney(user, money);

        // 检测当天提取次数
        if (result.isSuccess()) {
            result = validSingleDayTime(user);
        }

        // 检测一次提取最大额度
        if (result.isSuccess()) {
            result = validSingleMaxAmount(user, money);
        }

        // 检测一次提取最小额度
        if (result.isSuccess()) {
            result = validSingleMinAmount(money);
        }

        // 检测当天提取额度
        if (result.isSuccess()) {
            result = validSingleDayMaxAmount(user, money);
        }

        //检测银行卡是否存在
        if (result.isSuccess()) {
            result = validBindingBank(user, bankNo);
        }

        return result;
    }

    /**
     * 检测可用金额
     *
     * @param user
     * @param money
     * @return
     */
    private ReturnResult validUseMoney(User user, double money) {
        Account account = accountService.findAccountByUserId(user.getUserId());
        if (account.getUseMoney() < money) {
            return new ReturnResult("提现金额不能大于账户可用余额!");
        }
        return ReturnResult.SUCCESS;
    }

    /**
     * 当天提现次数限制
     *
     * @param user
     * @return
     */
    private ReturnResult validSingleDayTime(User user) {
        SystemConfig config = SystemConfigHelper.getSystemConfig(Nid.CASH_SINGLE_DAY_TIME_LIMIT);
        if (config.getStatus() == 1) {
            int singleDayTime = accountCashService.getSingleDaytime(user.getUserId());
            int singleDayTimeLimit = DataUtils.toInt(config.getValue());
            if (singleDayTime >= singleDayTimeLimit) {
                return new ReturnResult("今日提现次数已用完,每天最多只能提现" + singleDayTimeLimit + "次!");
            }
        }
        return ReturnResult.SUCCESS;
    }

    /**
     * 最高单笔提现额度限制
     *
     * @param user
     * @param money
     * @return
     */
    private ReturnResult validSingleMaxAmount(User user, double money) {

        // 企业借款人
        boolean isCompany = UserTypeUtils.isBorrowOrInverstment(user.getUserId());
        SystemConfig config;
        if (isCompany) {
            config = SystemConfigHelper.getSystemConfig(Nid.COMP_CASH_SINGLE_MAX_AMOUNT_LIMIT);
        } else {
            config = SystemConfigHelper.getSystemConfig(Nid.CASH_SINGLE_MAX_AMOUNT_LIMIT);
        }

        if (config.getStatus() == 1) {
            double singleCompMaxAmountLimit = DataUtils.toDouble(config.getValue());
            if (money > singleCompMaxAmountLimit) {
                return new ReturnResult("提现失败,单笔提现不能超过" + NumberUtil.format2Str(singleCompMaxAmountLimit) + "元!");
            }
        }

        return ReturnResult.SUCCESS;
    }

    /**
     * 最低单笔提现额度限制
     *
     * @param money
     * @return
     */
    private ReturnResult validSingleMinAmount(double money) {
        SystemConfig config = SystemConfigHelper.getSystemConfig(Nid.CASH_SINGLE_MIN_AMOUNT_LIMIT);
        if (config.getStatus() == 1) {
            double singleMinAmountLimit = DataUtils.toDouble(config.getValue());
            if (money < singleMinAmountLimit) {
                return new ReturnResult("提现失败,单笔提现不能低于" + NumberUtil.format2Str(singleMinAmountLimit) + "元!");
            }
        }
        return ReturnResult.SUCCESS;
    }

    /**
     * 单日提现额度限制
     */
    private ReturnResult validSingleDayMaxAmount(User user, double money) {
        SystemConfig config = SystemConfigHelper.getSystemConfig(Nid.CASH_SINGLE_DAY_MAX_AMOUNT_LIMIT);
        if (config.getStatus() == 1) {
            double singleDayAmount = accountCashService.getSingleDayAmount(user.getUserId());
            double singleDayMaxAmountLimit = DataUtils.toDouble(config.getValue());
            if ((money + singleDayAmount) > singleDayMaxAmountLimit) {
                double c = singleDayMaxAmountLimit - singleDayAmount;
                String msg;
                if (c > 0) {
                    msg = "提现失败,您今天还可提现" + NumberUtil.format2Str(c) + "元!";
                } else {
                    msg = "提现失败,您今天提现已达限额" + NumberUtil.format2Str(singleDayMaxAmountLimit) + "元!";
                }
                return new ReturnResult(msg);
            }
        }
        return ReturnResult.SUCCESS;
    }

    /**
     * 检测银行卡是否存在
     *
     * @param user
     * @param bankNo
     * @return
     */
    private ReturnResult validBindingBank(User user, String bankNo) {

        // 数据库获取银行卡
        AccountBank accountBank = accountBankService.find(user.getUserId(), bankNo);
        if (accountBank == null) {
            return new ReturnResult("获取银行卡信息失败!");
        }

        // 支付接口获取银行卡
        if(UserTypeUtils.isCorporate(user.getUserId())){
        	BankCardListForEnterpriseParameter parameter = new BankCardListForEnterpriseParameter();
        	parameter.setPlatformUserId(user.getTppUserCustId());
        	BankCardListForEnterpriseResponse response = adaptedPayService.queryBankListForEnterprise(parameter);
        	BankCardListForEnterpriseResponse.Bank bank = response.getBank(bankNo);
        	if(bank == null){
        		return new ReturnResult("银行卡绑卡有误，请重新绑定！");
        	}
        }else{
        	BankCardListParameter parameter = new BankCardListParameter();
        	parameter.setPlatformUserId(user.getTppUserCustId());
        	BankCardListResponse response = adaptedPayService.queryBankList(parameter);
        	if(response == null){
        		return new ReturnResult("获取银行卡信息失败!");
        	}
        	
        	String cardId = accountBank.getTppCardId();
        	Bank bank = response.getBank(cardId);
        	if(bank == null){
        		return new ReturnResult("银行卡绑卡有误，请重新绑定！");
        	}
        	
        	//判断银行卡后4位是否一致
        	boolean hasFindCard = false;
        	String accountNo = null;
        	accountNo = bank.getBankNo();
        	
        	String suffixAccountNo = accountNo.substring(accountNo.length() - 4, accountNo.length());
        	if (accountBank.getBankNo().endsWith(suffixAccountNo)) {
        		hasFindCard = true;
        	}
        	if (!hasFindCard) {
        		return new ReturnResult("银行卡绑卡有误，请重新绑定！");
        	}
        }

        ReturnResult result = new ReturnResult();
        result.addExtra("accountBank", accountBank);
        return result;
    }

	/**
	 * 冻结提取资金，保存提取记录
	 * @param user
	 * @param accountCash
	 * @author linya
	 */
	protected void saveAccountCash(User user, AccountCash accountCash){
		// 冻结资金
		Global.setTransfer(LogTplNid.LOG_TPL_KEY, LogTplNid.CASH_APPLY);
		Global.setTransfer("cash", accountCash);
		Global.setTransfer("ip", accountCash.getAddIp());
		double money = accountCash.getMoney();
		accountService.freeze(user.getUserId(), SystemConfigs.ADMIN_ID, money);
		// 保存提取记录
		accountCash.setStatus(AccountCashStatus.APPLY);
		accountCashService.save(accountCash);
	}
}
